#include "asr.h"
#include <QDebug>
#include <QNetworkRequest>
#include <QJsonParseError>
#include <QFileInfo>
#include <QCryptographicHash>
#include <QAudioDecoder>
#include <QEventLoop>
#include <QUuid>
#include <QProcess>
#include<QDir>
Asr::Asr(QWidget *parent) : QWidget(parent)
{
    networkAccessManager = new QNetworkAccessManager(this);
    connect(networkAccessManager, &QNetworkAccessManager::finished,
            this, &Asr::handleNetworkReply);
}

Asr::~Asr()
{
    networkAccessManager->deleteLater();
}

void Asr::getTheResult(const QString &fileName)
{
    QFileInfo fileInfo(fileName);
    if (!fileInfo.exists() || fileInfo.size() < 1024) {
        emit asrReadyData("ERROR: 无效的音频文件");
        return;
    }

    if (accessToken.isEmpty()) {
        if (!isProcessing) {
            isProcessing = true;
            pendingAudioFile = fileName;
            requestToken();
        }
        return;
    }

    processAudioFile(fileName);
}

void Asr::requestToken()
{
    QNetworkRequest request;
    request.setUrl(QUrl(tokenUrl));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    networkAccessManager->get(request);
}

void Asr::sendSpeechRequest(const QByteArray &jsonData)
{
    QNetworkRequest request;
    request.setUrl(QUrl(serverApiUrl));
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

    QNetworkReply *reply = networkAccessManager->post(request, jsonData);

    QTimer::singleShot(10000, this, [this, reply]() {
        if (reply && reply->isRunning()) {
            reply->abort();
            emit asrReadyData("ERROR: 请求超时");
        }
    });
}

bool Asr::verifyAudioFormat(const QString &fileName, int &outSampleRate)
{
    QAudioDecoder decoder;
    decoder.setSourceFilename(fileName);

    QEventLoop loop;
    bool formatReceived = false;

    connect(&decoder, &QAudioDecoder::formatChanged, [&](const QAudioFormat &format) {
        outSampleRate = format.sampleRate();
        formatReceived = true;
        loop.quit();
    });

    decoder.start();
    QTimer::singleShot(1000, &loop, &QEventLoop::quit);
    loop.exec();

    return formatReceived;
}

bool Asr::resampleAudio(const QString &inputFile, const QString &outputFile, int targetRate)
{
    QProcess ffmpeg;
    ffmpeg.start("ffmpeg", {
        "-i", inputFile,
        "-ar", QString::number(targetRate),
        "-ac", "1",
        "-y",
        outputFile
    });

    return ffmpeg.waitForFinished(5000);
}

void Asr::processAudioFile(const QString &fileName)
{
    QString audioFileToProcess = fileName;
    int actualRate = 0;

    if (!verifyAudioFormat(fileName, actualRate)) {
        emit asrReadyData("ERROR: 无法读取音频参数");
        return;
    }

    if (actualRate != 16000) {
        QString resampledFile = QDir::tempPath() + "/" + QUuid::createUuid().toString() + ".wav";
        if (!resampleAudio(fileName, resampledFile, 16000)) {
            emit asrReadyData("ERROR: 音频重采样失败");
            return;
        }
        audioFileToProcess = resampledFile;
    }

    QFile file(audioFileToProcess);
    if (!file.open(QIODevice::ReadOnly)) {
        emit asrReadyData("ERROR: 无法打开音频文件");
        return;
    }

    QByteArray audioData = file.readAll();
    file.close();

    QJsonObject json;
    json.insert("format", "wav");
    json.insert("rate", 16000);
    json.insert("channel", 1);
    json.insert("token", accessToken);
    json.insert("cuid", QHostInfo::localHostName());
    json.insert("len", audioData.size());
    json.insert("speech", QString(audioData.toBase64()));

    sendSpeechRequest(QJsonDocument(json).toJson());

    if (audioFileToProcess != fileName) {
        QFile::remove(audioFileToProcess);
    }
}

void Asr::handleNetworkReply(QNetworkReply *reply)
{
    if (!reply) return;

    QByteArray data;
    if (reply->error() == QNetworkReply::NoError) {
        data = reply->readAll();
    } else {
        qDebug() << "网络错误:" << reply->errorString();
        emit asrReadyData("ERROR: " + reply->errorString());
        reply->deleteLater();
        return;
    }

    if (reply->url().toString().contains("oauth/2.0/token")) {
        processTokenResponse(data);
    } else {
        processSpeechResponse(data);
    }

    reply->deleteLater();
}

void Asr::processTokenResponse(const QByteArray &data)
{
    isProcessing = false;

    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(data, &error);

    if (error.error != QJsonParseError::NoError) {
        emit asrReadyData("ERROR: 无效的Token响应");
        return;
    }

    QJsonObject obj = doc.object();
    accessToken = obj["access_token"].toString();

    if (accessToken.isEmpty()) {
        emit asrReadyData("ERROR: 无效的Token");
        return;
    }

    serverApiUrl = serverApiTemplate.arg(QHostInfo::localHostName()).arg(accessToken);

    if (!pendingAudioFile.isEmpty()) {
        processAudioFile(pendingAudioFile);
        pendingAudioFile.clear();
    }
}

void Asr::processSpeechResponse(const QByteArray &data)
{
    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(data, &error);

    if (error.error != QJsonParseError::NoError) {
        emit asrReadyData("ERROR: 无效的识别响应");
        return;
    }

    QJsonObject obj = doc.object();

    if (obj.contains("err_no")) {
        int errCode = obj["err_no"].toInt();
        QString errMsg = obj.value("err_msg").toString("未知错误");
        emit asrReadyData(QString("ERROR[%1]: %2").arg(errCode).arg(errMsg));
        return;
    }

    if (obj.contains("result") && obj["result"].isArray()) {
        QJsonArray results = obj["result"].toArray();
        if (!results.isEmpty() && results[0].isString()) {
            emit asrReadyData(results[0].toString());
            return;
        }
    }

    emit asrReadyData("ERROR: 无法解析识别结果");
}
